﻿namespace PillBox.Client.Model
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Reflection;
    using System.Threading;
    using PillBox.Client.ViewModels;

    [Export(typeof(IDataService))]
    public class FakeDataService : IDataService
    {
        private readonly IEnumerable<MethodInfo> _methods = typeof(FakeDataService).GetMethods().Where(x => x.Name == "Handle");

        private readonly List<Person> _people = new List<Person>
        {
            new Person
            {
                PersonID = 1,
                Name = "Frank",
                Role = PersonRole.Patient,
                ColorBand = "#FF238823",
                ImageUri = "/PillBox.Client;component/Resources/Images/frank1_40.png",
                FullSizeImageUri = "/PillBox.Client;component/Resources/Images/frank1_95.png",
                Email = "frank@aol.com",
            },
            new Person
            {
                PersonID = 2,
                Name = "Ethel",
                Role = PersonRole.Patient,
                ColorBand = "#FF9A2EA3",
                ImageUri = "/PillBox.Client;component/Resources/Images/ethel1_40.png",
                FullSizeImageUri = "/PillBox.Client;component/Resources/Images/ethel1_95.png",
                Email = "ethel@aol.com",
            },
            new Person
            {
                PersonID = 3,
                Name = "Jessica",
                Role = PersonRole.Caregiver,
                ImageUri = "/PillBox.Client;component/Resources/Images/jessica1_40.jpg",
                FullSizeImageUri = "/PillBox.Client;component/Resources/Images/jessica1_95.jpg",
                Email = "jess@hotmail.com",
            },
            new Person
            {
                PersonID = 4,
                Name = "Issac",
                Role = PersonRole.Caregiver,
                ImageUri = "/PillBox.Client;component/Resources/Images/isaac2_40.jpg",
                FullSizeImageUri = "/PillBox.Client;component/Resources/Images/isaac2_95.jpg",
                Email = "issac@hotmail.com",

            },
            new Person
            {
                PersonID = 5,
                Name = "Dr. Pride",
                Role = PersonRole.Doctor,
                ImageUri = "/PillBox.Client;component/Resources/Images/charlie_40.jpg",
                FullSizeImageUri = "/PillBox.Client;component/Resources/Images/charlie_95.jpg",
                Email = "cpride@mbqhc.com",
            }
        };

        private readonly List<Medication> _medications = new List<Medication>
        {
            new Medication
            {
                MedicineID = 1,
                Name = "Keflex",
                Dosage = "5mg",
				Frequency = "once every morning",
                DeliveryMethod = DeliveryMethod.Mouth,
                ImageUri = "/PillBox.Client;component/Resources/Images/keflex.png",
                Expiration = "4/21/10",
				Description = "Keflex is an antibiotic.",
				MoreInfoUri = "http://drugs.com/keflex.html",
                PrescriberID = 5,
                PersonID = 2,
            },
            new Medication
            {
                MedicineID = 2,
                Name = "Metoprolol",
                Dosage = "50mg",
				Frequency = "twice a day",
                DeliveryMethod = DeliveryMethod.Mouth,
                ImageUri = "/PillBox.Client;component/Resources/Images/metoprolol.png",
                Expiration = "4/21/10",
				Description = "Metoprolol is a beta-blocker used to treat chest pain and high blood pressure.",
                MoreInfoUri = "http://drugs.com/metoprolol.html",
                PrescriberID = 5,
                PersonID = 2,
            },
            new Medication
            {
                MedicineID = 3,
                Name = "Prevacid",
                Dosage = "30mg",
				Frequency = "once a day",
                DeliveryMethod = DeliveryMethod.Mouth,
                ImageUri = "/PillBox.Client;component/Resources/Images/Prevacid-15-mg_frnt.png",
                Expiration = "4/21/10",
				Description = "Prevacid is an antacid used to treat heartburn and acid reflux.",
                MoreInfoUri = "http://drugs.com/prevacid.html",
				PrescriberID = 5,
                PersonID = 1,
            },
            new Medication
            {
                MedicineID = 4,
                Name = "Neurontin",
                Dosage = "600mg",
				Frequency = "every 4 hours",
                DeliveryMethod = DeliveryMethod.Mouth,
                ImageUri = "/PillBox.Client;component/Resources/Images/Neurontin-600-mg_frnt.png",
                Expiration = "4/21/10",
				Description = "Neurontin is an anticonvulsant that is also used to treat nerve pain.  Antacids can make it harder for the body to absorb neurontin, so avoid taking neurontin within 2 hours before or after taking an antacid.",
                MoreInfoUri = "http://drugs.com/neurontin.html",
				PrescriberID = 5,
                PersonID = 1,
            },
            new Medication
            {
                MedicineID = 5,
                Name = "Percocet",
                Dosage = "5/325mg",
				Frequency = "twice daily",
                DeliveryMethod = DeliveryMethod.Mouth,
                ImageUri = "/PillBox.Client;component/Resources/Images/Percocet-325-5-mg_frnt.png",
                Description = "Percocet is a narcotic pain reliever. It is a combination of acetaminophen and oxycodone.",
                MoreInfoUri = "http://drugs.com/percocet.html",
				Expiration = "4/21/10",
                PrescriberID = 5,
                PersonID = 2,
            },
        };

        private readonly List<Note> _notes = new List<Note>
        {
            // ********** uncomment these notes for Jessica's scene ********* //
            new Note
            {
                From = "Isaac",
                ColorBand="#FF238823",
                Message = "Ensured that Frank took his prevacid, and he was feeling MUCH better at dinner tonight.",
                Date = DateTime.Today.AddHours(19).AddMinutes(06)
            },
            new Note
            {
                From = "Isaac",
                ColorBand= "#FF9A2EA3",
                Message = "Back from Dr. Pride's office. Ethel was cranky; wouldn't take meds; turned out to be UTI. Doc gave her antibiotics. She's on mend. No worries!",
                Date = DateTime.Today.AddHours(14).AddMinutes(41)
            },
            new Note
            {
                From = "Dr. Pride",
                ColorBand = "#FF9A2EA3",
                Message = "I've prescribed 3 days of Keflex for Ethel's urinary tract infection. (Have her drink cranberry juice, too.)",
                Date = DateTime.Today.AddHours(13).AddMinutes(40)
            },
            // ********** uncomment this note for after Isaac wakes up ********** //
            new Note
            {
                From = "Jessica",
                ColorBand = "#FF238823",
                Message = "Frank missed his noon antacid the past couple days and was having heartburn in eve. Can you ensure he takes it while we're gone? Thanks!",
                Date = DateTime.Today.AddHours(7).AddMinutes(14)
            },
			new Note
			{
				From = "Jessica",
				Message = "Roger and I are leaving on vacation this weekend, just in case you didn't see my twenty e-mails saying so. :)",
				Date = DateTime.Today.AddDays(-2).AddHours(19).AddMinutes(2)
			},
			new Note
			{
				From = "Me",
				ColorBand = "#FF238823",
				Message = "Frank fell out of bed last night and hurt his shoulder. I drove him to the doctor's office, and X-rays showed nothing wrong. He's nursing motrin and wounded ego.",
				Date = DateTime.Today.AddDays(-15).AddHours(8).AddMinutes(13)
			},	
			new Note
            {
                From = "Dr. Pride",
				ColorBand = "#FF9A2EA3",
                Message = "I've put Ethel on Keflex for her UTI.  Make sure that she doesn't miss any doses, and she should be good to go after 3 days.",
                Date = DateTime.Today.AddDays(-30).AddHours(1).AddMinutes(28)
            }
        };

        private readonly List<Schedule> _schedules = new List<Schedule>
        {
            new Schedule
            {
                PersonID = 1,
                MedicineID = 3,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 7, 0, 0),
            },
            new Schedule
            {
                PersonID = 2,
                MedicineID = 2,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 7, 0, 0),
            },
            new Schedule
            {
                PersonID = 1,
                MedicineID = 4,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 9, 0, 0),
            },
            new Schedule
            {
                PersonID = 1,
                MedicineID = 3,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 12, 0, 0),
            },
            new Schedule
            {
                PersonID = 2,
                MedicineID = 2,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 12, 30, 0),
            },
            new Schedule
            {
                PersonID = 1,
                MedicineID = 3,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 17, 0, 0),
            },
            new Schedule
            {
                PersonID = 2,
                MedicineID = 2,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 17, 0, 0),
            },
            new Schedule
            {
                PersonID = 2,
                MedicineID = 5,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 20, 30, 0),
            },
            new Schedule
            {
                PersonID = 1,
                MedicineID = 4,
                TimeOfDay = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 21, 0, 0),
            },
        };

        public void Send(IDataCommand command)
        {
            Invoke(command, command);
        }

        public void Send<TResponse>(IQuery<TResponse> query, Action<TResponse> reply)
        {
            Invoke(query, query, reply);
        }

        private void Invoke(object request, params object[] args)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                var requestType = request.GetType();
                var handler = _methods.Where(x => requestType.IsAssignableFrom(x.GetParameters().First().ParameterType)).First();

                handler.Invoke(this, args);
            });
        }

        public void Handle(GetPeopleQuery search, Action<IEnumerable<Person>> reply)
        {
            if (search.Filter != null)
            {
                reply(_people.Where(search.Filter));
            }
            else
            {
                reply(_people);
            }
        }

        public void Handle(GetMedicationQuery search, Action<IEnumerable<Medication>> reply)
        {
            if (_medications[0].Prescriber == null || _medications[0].Person == null)
            {
                _medications.ForEach(
                x =>
                {
                    x.Prescriber = _people.First(p => p.PersonID == x.PrescriberID);
                    x.Person = _people.First(p => p.PersonID == x.PersonID);
                });
            }

            reply(_medications);
        }

        public void Handle(GetNotesQuery search, Action<IEnumerable<Note>> reply)
        {
            reply(_notes);
        }

        public void Handle(GetScheduleQuery search, Action<IEnumerable<ScheduleDayViewModel>> reply)
        {
            if (search.PersonID > 0)
            {
                var results = from x in this._schedules
                              where x.PersonID == search.PersonID
                              select new ScheduleDayItemViewModel
                              {
                                  Person = _people.First(p => p.PersonID == x.PersonID),
                                  Medication = _medications.First(m => m.MedicineID == x.MedicineID),
                                  TimeOfDay = x.TimeOfDay
                              };

                reply(CreateSchedule(search.Date, results));
            }
            else
            {
                var results = from x in this._schedules
                                  select new ScheduleDayItemViewModel
                                  {
                                      Person = _people.First(p=>p.PersonID == x.PersonID),
                                      Medication = _medications.First(m=>m.MedicineID == x.MedicineID),
                                      TimeOfDay = x.TimeOfDay
                                  };

                reply(CreateSchedule(search.Date, results));
            }
        }

        private IEnumerable<ScheduleDayViewModel> CreateSchedule(DateTime date, IEnumerable<ScheduleDayItemViewModel> results)
        {
            List<ScheduleDayViewModel> schedule = new List<ScheduleDayViewModel>();

            int dayOfWeek = (int)date.DayOfWeek;

            for (int i = 0; i < dayOfWeek; i++)
            {
                schedule.Add(new ScheduleDayViewModel(date.AddDays((i - dayOfWeek)), results));
            }

            for (int i = dayOfWeek; i < 7; i++)
            {
                schedule.Add(new ScheduleDayViewModel(date.AddDays(i - dayOfWeek), results));
            }

            return schedule;
        }
    }
}